/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package linkeddata.arida.ufc.br.VCD;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

/**
 *
 * @author jeovane
 */
public class ExtractsContentVCD extends ElementsVCDS {

    private SAXBuilder builder = new SAXBuilder();
    private Document document;
    private Element root;
    private ElementsVCDS elementsVCDS;

    public ExtractsContentVCD(File file) {
        try {
            this.document = builder.build(file);
            this.root = document.getRootElement();
        } catch (JDOMException ex) {
            System.out.println("JDOMException: " + ex);
        } catch (IOException ex) {
            System.out.println("IOException: " + ex);
        }
    }

    // Obtém o nome da VCD corrente
    public String getNameVCD() {
        return root.getAttribute("name").getValue().toLowerCase();
    }

    // Obtém a VCD cujo valor contigo no atributo "primary" é ON
    public String getVCDMain() {
        if (root.getAttribute("type").getValue().equalsIgnoreCase("Initial")) {
            return getNameVCD().toLowerCase();
        }
        return null;
    }

    // Extrai as variáveis que ficarão na query
    public List<String> getVariablesSelect() {
        String variablesSelect = root.getChild("ParameterList").getChild("Select").getChildText("Variables");
        List<String> listVariables = new ArrayList<String>();
        StringTokenizer st = new StringTokenizer(variablesSelect, ", ");

        while (st.hasMoreTokens()) {
            listVariables.add(st.nextToken());
        }
        return listVariables;
    }

    // Obtém o LIMIT de cada VCD para ser relacionado com a sua query
    public String getLimit() {
        if (!"".equals(root.getChild("ParameterList").getChild("Limit").getText())) {
            return "LIMIT " + root.getChild("ParameterList").getChild("Limit").getText();
        }
        return "";
    }

    // Obtém a condição de ordenação de cada VCD se existir e a releciona com a query correspondente
    public String getCondition() {
        List<Element> queryCondition = root.getChild("ParameterList").getChildren("Sort-condition");

        if (!queryCondition.isEmpty()) {
            for (int i = 0; i < queryCondition.size(); i++) {
                Element elementParameter = queryCondition.get(i);
                List parameterColumn = elementParameter.getChildren("Attribute");
                for (int j = 0; j < parameterColumn.size(); j++) {
                    Element object = (Element) parameterColumn.get(j);
                    if (!"".equals(object.getAttributeValue("operator"))) {
                        return object.getAttributeValue("operator") + " ?" + object.getText();
                    }
                }
            }
        }

        return "";
    }

    // Extrai os elementos contidos na tag <elos>
    public List<ElementsVCDS> getElosVCD() {
        List<ElementsVCDS> listElos = new ArrayList<ElementsVCDS>();
        List<Element> rowElos = root.getChildren("Elos");

        for (int i = 0; i < rowElos.size(); i++) {
            Element elos = rowElos.get(i);
            List elosColumn = elos.getChildren();

            for (int j = 0; j < elosColumn.size(); j++) {
                Element parameters = (Element) elosColumn.get(j);
                List pElos = parameters.getChildren();

                for (int k = 0; k < pElos.size(); k++) {
                    Element eDestination = (Element) pElos.get(k);
                    List pParameter = eDestination.getChildren();
                    String nameDestination = eDestination.getAttribute("vcd").getValue();

                    for (int l = 0; l < pParameter.size(); l++) {
                        String valueParameter = eDestination.getChildren().get(l).getValue().toString();

                        elementsVCDS = new ElementsVCDS();
                        elementsVCDS.setNameVCDExtract(getNameVCD());
                        elementsVCDS.setDestinationVCD(nameDestination.toLowerCase());
                        elementsVCDS.setParameter(valueParameter.toLowerCase());

                        listElos.add(elementsVCDS);
                    }
                }
            }
        }
        return listElos;
    }

    // Obtém o Endpoint contido em cada VCD
    public String getServiceURI() {
        return root.getChild("SPARQLQuery").getChild("Operator").getChild("Query").getAttributeValue("serviceURI");
    }

    // Extrai a query contida nas VCD
    public List<ElementsVCDS> extractQueryVCD() {
        List query = root.getChild("SPARQLQuery").getChildren("Operator");
        List<ElementsVCDS> queryList = new ArrayList<ElementsVCDS>();

        for (int i = 0; i < query.size(); i++) {
            Element operator = (Element) query.get(i);
            List listOperator = operator.getChildren();
            for (int j = 0; j < listOperator.size(); j++) {
                Element elementOp = (Element) listOperator.get(j);
                String service = elementOp.getAttributeValue("serviceURI");
                String queryText = elementOp.getText();
                String prefix = queryText.substring(0, queryText.indexOf("SELECT"));
                String strEnd = queryText.substring(queryText.indexOf("{") + 1, queryText.lastIndexOf("}"));

                elementsVCDS = new ElementsVCDS();
                elementsVCDS.setNameVCDExtract(getNameVCD());
                elementsVCDS.setPrefix(prefix);
                elementsVCDS.setService(service);
                elementsVCDS.setWhere(strEnd);

                queryList.add(elementsVCDS);
            }
        }

        return queryList;
    }
    
    // Extrai os Services das querys contida na VCD
    public Map<String, ArrayList<String>> getServicesVCDS() {
        String VCDKey = root.getAttribute("name").getValue();
        List queryServices = root.getChild("SPARQLQuery").getChildren("Operator");

        Map<String, ArrayList<String>> mapMandatoryAttr = new LinkedHashMap<String, ArrayList<String>>();
        ArrayList<String> schema;
        ArrayList<String> schemaExisting;

        for (int i = 0; i < queryServices.size(); i++) {
            Element attribute = (Element) queryServices.get(i);
            List listAttributes = attribute.getChildren();
            for (int j = 0; j < listAttributes.size(); j++) {
                Element eClazz = (Element) listAttributes.get(j);
                String servicesURI = eClazz.getAttribute("serviceURI").getValue();

                if (mapMandatoryAttr.containsKey(VCDKey)) {
                    schemaExisting = mapMandatoryAttr.get(VCDKey);
                    schemaExisting.add(servicesURI);
                    mapMandatoryAttr.put(VCDKey, schemaExisting);
                } else {
                    schema = new ArrayList<String>();
                    schema.add(servicesURI);
                    mapMandatoryAttr.put(VCDKey, schema);
                }
            }
        }
        return mapMandatoryAttr;
    }
}
